﻿namespace LHA.Parsing.HTML
{
    using System.Collections.Generic;
    using System.Text.RegularExpressions;

    /// <summary>
    /// Class that 
    /// [LHA]: 03/2010 (mailto:lha.dev@gmail.com)
    /// </summary>
    public class Parser
    {

        #region .: CONSTANTS :.

        private const string REGEX_PATTERN_4_TAG = "<(?<tag>[^<>]+)>";  // == <[tag]>
        private const string REGEX_PATTERN_4_ATTRIBUTE = "(?<name>[^ \"]+)=\"(?<value>[^\"]+)\"";  // == [key]="[value]", does not work for empty key/value!

        #endregion

        #region .: fields :.

        private Regex _attRegex;

        #endregion

        #region .: props :.

        private Regex AttributeRegex
        {
            get
            {
                if (this._attRegex == null)
                    this._attRegex = new Regex(REGEX_PATTERN_4_ATTRIBUTE, RegexOptions.Compiled);
                return this._attRegex;
            }
        }

        #endregion

        #region .: protected methods :.

        protected virtual Dictionary<string, string> GetTagAttributes(string TagString)
        {
            Dictionary<string, string> result = new Dictionary<string, string>();

            MatchCollection attributes = this.AttributeRegex.Matches(TagString);

            if (attributes.Count > 0)
            {
                foreach (Match attribute in attributes)
                {
                    result.Add(attribute.Groups["name"].Value, attribute.Groups["value"].Value);
                }
            }

            return result;
        }

        protected virtual string GetTagName(string TagString)
        {
            string[] tokens = TagString.Split(' ');
            return tokens[0];

        }

        protected virtual bool ParseTag(string TagString)
        {
            return TagString[0] != '!';  //means the comments will not be processed
        }

        #endregion

        #region .: public methods :.

        public List<TagItem> Parse(string Source)
        {
            List<TagItem> result = new List<TagItem>();

            MatchCollection matches = Regex.Matches(Source, REGEX_PATTERN_4_TAG);

            if (matches.Count > 0)
            {
                string tagString;
                foreach (Match m in matches)
                {
                    tagString = m.Groups["tag"].Value;

                    if (this.ParseTag(tagString))  // apply the filter
                        result.Add(new TagItem(this.GetTagName(tagString), this.GetTagAttributes(tagString)));
                }
            }

            return result;
        }

        public void ParseHierarchically(string Source)
        {
            /*            foreach (TagItem ti in tags)
            {
                this.txtOutput.Text += string.Format("{0}: {1}{2}", counter++, tag, "\r\n");

                switch (tag[0])
                {
                    case '!':  // comment

                        break;
                    case '/':  // => ending tag

                        if (stack.Peek().Tag.IndexOf(tag.Substring(1, tag.Length - 2).Trim()) > -1)
                        {
                            temp = stack.Pop();
                            if (stack.Count > 0)
                                stack.Peek().Children.Add(temp);
                        }
                        else
                        {
                            throw new ApplicationException(string.Format("Inappropriate ending tag {0} after tag {1} at position {2}", tag, stack.Peek(), m.Index));
                        }
                        break;
                    default:
                        if (tag[tag.Length - 1] == '/') // => single tag
                        {
                            stack.Peek().Children.Add(new TagNode() { Tag = tag, Children = null });
                        }
                        else
                        {
                            stack.Push(new TagNode() { Tag = tag, Children = new List<TagNode>() });
                        }
                        break;
                }
            }
*/
        }

        #endregion

    }
}
